package com.joker.airoleplayplatformback.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * WAV文件处理工具类
 * 用于创建和处理标准WAV格式的音频文件
 *
 * @author feixiang.li
 * @since 2025-09-27
 */
@Slf4j
public class WavFileUtils {

    // WAV文件头常量
    private static final String RIFF_HEADER = "RIFF";
    private static final String WAVE_FORMAT = "WAVE";
    private static final String FMT_CHUNK = "fmt ";
    private static final String DATA_CHUNK = "data";
    
    // 音频参数
    private static final int SAMPLE_RATE = 16000;
    private static final int CHANNELS = 1;
    private static final int BITS_PER_SAMPLE = 16;
    private static final int BYTE_RATE = SAMPLE_RATE * CHANNELS * BITS_PER_SAMPLE / 8;
    private static final int BLOCK_ALIGN = CHANNELS * BITS_PER_SAMPLE / 8;

    /**
     * 将原始音频数据转换为标准WAV文件
     *
     * @param rawAudioData 原始音频数据
     * @param outputPath   输出文件路径
     * @return 是否转换成功
     */
    public static boolean convertToWav(byte[] rawAudioData, String outputPath) {
        try {
            File outputFile = new File(outputPath);
            
            try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                // 写入WAV文件头
                writeWavHeader(fos, rawAudioData.length);
                
                // 写入音频数据
                fos.write(rawAudioData);
                
                log.info("WAV文件创建成功: {}, 大小: {} bytes", outputPath, outputFile.length());
                return true;
            }
            
        } catch (Exception e) {
            log.error("创建WAV文件失败: {}", outputPath, e);
            return false;
        }
    }

    /**
     * 写入WAV文件头
     */
    private static void writeWavHeader(OutputStream os, int dataSize) throws IOException {
        // RIFF header
        os.write(RIFF_HEADER.getBytes());
        os.write(intToLittleEndian(36 + dataSize)); // 文件大小
        os.write(WAVE_FORMAT.getBytes());
        
        // fmt chunk
        os.write(FMT_CHUNK.getBytes());
        os.write(intToLittleEndian(16)); // fmt chunk size
        os.write(shortToLittleEndian((short) 1)); // audio format (PCM)
        os.write(shortToLittleEndian((short) CHANNELS)); // number of channels
        os.write(intToLittleEndian(SAMPLE_RATE)); // sample rate
        os.write(intToLittleEndian(BYTE_RATE)); // byte rate
        os.write(shortToLittleEndian((short) BLOCK_ALIGN)); // block align
        os.write(shortToLittleEndian((short) BITS_PER_SAMPLE)); // bits per sample
        
        // data chunk
        os.write(DATA_CHUNK.getBytes());
        os.write(intToLittleEndian(dataSize)); // data size
    }

    /**
     * 验证WAV文件格式
     */
    public static boolean isValidWavFile(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] header = new byte[12];
            if (fis.read(header) < 12) {
                return false;
            }
            
            // 检查RIFF头
            String riffHeader = new String(header, 0, 4);
            if (!RIFF_HEADER.equals(riffHeader)) {
                return false;
            }
            
            // 检查WAVE格式
            String waveFormat = new String(header, 8, 4);
            return WAVE_FORMAT.equals(waveFormat);
            
        } catch (Exception e) {
            log.error("验证WAV文件失败: {}", filePath, e);
            return false;
        }
    }

    /**
     * 获取WAV文件信息
     */
    public static WavFileInfo getWavFileInfo(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] header = new byte[44]; // WAV文件头大小
            if (fis.read(header) < 44) {
                return null;
            }
            
            WavFileInfo info = new WavFileInfo();
            info.setFilePath(filePath);
            info.setFileName(new File(filePath).getName());
            
            // 解析文件头信息
            ByteBuffer buffer = ByteBuffer.wrap(header);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            
            // 跳过RIFF头
            buffer.position(22);
            info.setChannels(buffer.getShort());
            info.setSampleRate(buffer.getInt());
            info.setByteRate(buffer.getInt());
            info.setBlockAlign(buffer.getShort());
            info.setBitsPerSample(buffer.getShort());
            
            // 获取数据大小
            buffer.position(40);
            info.setDataSize(buffer.getInt());
            info.setFileSize(new File(filePath).length());
            
            return info;
            
        } catch (Exception e) {
            log.error("获取WAV文件信息失败: {}", filePath, e);
            return null;
        }
    }

    /**
     * 将int转换为小端序字节数组
     */
    private static byte[] intToLittleEndian(int value) {
        return ByteBuffer.allocate(4)
                .order(ByteOrder.LITTLE_ENDIAN)
                .putInt(value)
                .array();
    }

    /**
     * 将short转换为小端序字节数组
     */
    private static byte[] shortToLittleEndian(short value) {
        return ByteBuffer.allocate(2)
                .order(ByteOrder.LITTLE_ENDIAN)
                .putShort(value)
                .array();
    }

    /**
     * WAV文件信息类
     */
    public static class WavFileInfo {
        private String filePath;
        private String fileName;
        private int channels;
        private int sampleRate;
        private int byteRate;
        private int blockAlign;
        private int bitsPerSample;
        private int dataSize;
        private long fileSize;

        // Getters and Setters
        public String getFilePath() { return filePath; }
        public void setFilePath(String filePath) { this.filePath = filePath; }
        
        public String getFileName() { return fileName; }
        public void setFileName(String fileName) { this.fileName = fileName; }
        
        public int getChannels() { return channels; }
        public void setChannels(int channels) { this.channels = channels; }
        
        public int getSampleRate() { return sampleRate; }
        public void setSampleRate(int sampleRate) { this.sampleRate = sampleRate; }
        
        public int getByteRate() { return byteRate; }
        public void setByteRate(int byteRate) { this.byteRate = byteRate; }
        
        public int getBlockAlign() { return blockAlign; }
        public void setBlockAlign(int blockAlign) { this.blockAlign = blockAlign; }
        
        public int getBitsPerSample() { return bitsPerSample; }
        public void setBitsPerSample(int bitsPerSample) { this.bitsPerSample = bitsPerSample; }
        
        public int getDataSize() { return dataSize; }
        public void setDataSize(int dataSize) { this.dataSize = dataSize; }
        
        public long getFileSize() { return fileSize; }
        public void setFileSize(long fileSize) { this.fileSize = fileSize; }

        @Override
        public String toString() {
            return String.format("WavFileInfo{fileName='%s', channels=%d, sampleRate=%d, bitsPerSample=%d, dataSize=%d, fileSize=%d}", 
                fileName, channels, sampleRate, bitsPerSample, dataSize, fileSize);
        }
    }
}
